﻿using System;
using GeoAPI.Geometries;
using NetTopologySuite.Geometries;
using NetTopologySuite.Mathematics;

namespace NetTopologySuite.Shape.Fractal
{
	public class KochSnowflakeBuilder : GeometricShapeBuilder
	{
		public KochSnowflakeBuilder(IGeometryFactory geomFactory) : base(geomFactory)
		{
		}

		private static int RecursionLevelForSize(int numPts)
		{
			return (int)(Math.Log((double)numPts / 3.0) / Math.Log(4.0));
		}

		public override IGeometry GetGeometry()
		{
			int level = KochSnowflakeBuilder.RecursionLevelForSize(base.NumPoints);
			LineSegment squareBaseLine = base.GetSquareBaseLine();
			Coordinate[] boundary = this.GetBoundary(level, squareBaseLine.GetCoordinate(0), squareBaseLine.Length);
			return this.GeomFactory.CreatePolygon(this.GeomFactory.CreateLinearRing(boundary), null);
		}

		private Coordinate[] GetBoundary(int level, Coordinate origin, double width)
		{
			double num = origin.Y;
			if (level > 0)
			{
				num += KochSnowflakeBuilder.ThirdHeight * width;
			}
			Coordinate coordinate = new Coordinate(origin.X, num);
			Coordinate coordinate2 = new Coordinate(origin.X + width / 2.0, num + width * KochSnowflakeBuilder.HeightFactor);
			Coordinate coordinate3 = new Coordinate(origin.X + width, num);
			this.AddSide(level, coordinate, coordinate2);
			this.AddSide(level, coordinate2, coordinate3);
			this.AddSide(level, coordinate3, coordinate);
			this._coordList.CloseRing();
			return this._coordList.ToCoordinateArray();
		}

		private void AddSide(int level, Coordinate p0, Coordinate p1)
		{
			if (level == 0)
			{
				this.AddSegment(p0, p1);
				return;
			}
			Vector2D vector2D = Vector2D.Create(p0, p1);
			Coordinate coord = vector2D.Multiply(0.5).Translate(p0);
			Coordinate coordinate = vector2D.Multiply(KochSnowflakeBuilder.ThirdHeight).RotateByQuarterCircle(1).Translate(coord);
			int level2 = level - 1;
			Coordinate coordinate2 = vector2D.Multiply(0.33333333333333331).Translate(p0);
			Coordinate coordinate3 = vector2D.Multiply(0.66666666666666663).Translate(p0);
			this.AddSide(level2, p0, coordinate2);
			this.AddSide(level2, coordinate2, coordinate);
			this.AddSide(level2, coordinate, coordinate3);
			this.AddSide(level2, coordinate3, p1);
		}

		private void AddSegment(Coordinate p0, Coordinate p1)
		{
			this._coordList.Add(p1);
		}

		private readonly CoordinateList _coordList = new CoordinateList();

		private static readonly double HeightFactor = Math.Sin(1.0471975511965976);

		private const double OneThird = 0.33333333333333331;

		private static readonly double ThirdHeight = KochSnowflakeBuilder.HeightFactor / 3.0;

		private const double TwoThirds = 0.66666666666666663;
	}
}
